/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package extension.room.tienlen;

import extension.game.room.Player;
import extension.room.analyse.Card;
import extension.room.analyse.CardSet;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author daz
 */
public class TienlenPlayer extends Player {

    public static final int FINISH = 4;
    public static final int SKIP = 3;
    private boolean isRemainSpecialCard;
    private int numberSpcialCardRemains;
    private LinkedList<CardSet> listCardSets;

    public TienlenPlayer(String name, long money) {
        super(name, money, 0);
        this.name = name;
        this.money = money;
        rank = 100;
    }

    @Override
    public void resetCard() {
        listCardIds.clear();
        isRemainSpecialCard = false;
        this.numberSpcialCardRemains = 0;
        rank = 100;
    }

    public void addCard(int cardId) {
        listCardIds.add(cardId);
    }

    public void removeCardInHand(List<Integer> listRemove) {
        removeCard(listRemove);
        numberCardInHands -= listRemove.size();
    }

    private void removeCard(List<Integer> listRemove) {
        for (Integer remove : listRemove) {
            for (Integer card : listCardIds) {
                if (remove.equals(card)) {
                    listCardIds.remove(card);
                    break;
                }
            }
        }
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public int getRank() {
        return rank;
    }

    public void updateRank(int delta) {
        rank += delta;
    }

    public boolean checkRemainSpecialCard() {
        for (Integer cardId : listCardIds) {
            if (cardId % 13 == 1) {
                isRemainSpecialCard = true;
                this.numberSpcialCardRemains++;
            }
        }
        return false;
    }

    public boolean checkRemainCard() {
        for (Integer cardId : listCardIds) {
            if (cardId % 13 == 1) {
                isRemainSpecialCard = true;
                if (cardId / 13 < 2) {
                    this.numberSpcialCardRemains += 3;
                } else {
                    this.numberSpcialCardRemains += 4;
                }
            }
        }

        return false;
    }

    public boolean getIsRemainSpecialCard() {
        return isRemainSpecialCard;
    }

   

    void updateMoney(long moneyChange) {
        this.money += moneyChange;
    }

    public void moreSpecialCard() {
        this.numberSpcialCardRemains++;
    }

    public int getNumberSpcialCardRemains() {
        return numberSpcialCardRemains;
    }

    public List<Integer> getSuggestCard2(CardSet setFight) {
        listCardSets = new LinkedList<CardSet>();
        int[] listCards = new int[listCardIds.size()];
        for (int i = 0; i < listCardIds.size(); i++) {
            listCards[i] = listCardIds.get(i);
        }
        extractSpecialFlush(listCards);
        extractSpecialPair(listCards);
        return chooseBlockCard2(setFight);
    }

    public List<Integer> getSuggestCard(CardSet setFight) {
        listCardSets = new LinkedList<CardSet>();
        int[] listCards = new int[listCardIds.size()];
        for (int i = 0; i < listCardIds.size(); i++) {
            listCards[i] = listCardIds.get(i);
        }
        extractFlush(listCards);
        extractPair(listCards);
        return chooseBlockCard(setFight);
    }

    private List<Integer> chooseBlockCard(CardSet setFight) {
        // chan bo
        List<Integer> listBlock = new LinkedList<Integer>();
//        Debug.d("set fight :" + setFight.toString());
        for (CardSet set : listCardSets) {
            if (set.getType() == setFight.getType()
                    && set.getSetSize() >= setFight.getSetSize()) {
                listBlock.clear();
                if (set.getType() == CardSet.PAIR) {
                    boolean isChoose = true;
                    if (getCardValue(set.getCardId(0)) < getCardValue(setFight.getCardId(0))) {
                        isChoose = false;
                    } else if (set.getCardId(0) % 13 != 1) {
                        int startIndex = 0;
                        for (int i = 0; i < setFight.getSetSize(); i++) {
                            if (setFight.getCardId(0) / 13 == set.getCardId(i) / 13) {
                                startIndex = i;
                                break;
                            }
                        }
                        for (int i = startIndex; i < setFight.getSetSize(); i++) {
                            if (set.getCardId(i) / 13 != setFight.getCardId(i - startIndex) / 13) {
                                isChoose = false;
                                break;
                            }
                            listBlock.add(set.getCardId(i));
                        }
                    } else if (set.getCardId(0) % 13 == 1) {
                        for (int i = 0; i < setFight.getSetSize(); i++) {
                            listBlock.add(set.getCardId(i));
                        }
                    }
                    if (isChoose) {
//                        Debug.d("set :" + set.toString());
                        return listBlock;
                    }
                } else {
                    int suit1 = set.getCardId(0) / 13;
                    int suit2 = setFight.getCardId(0) / 13;
                    if (suit1 == suit2) {
                        int startIndex = 0;
                        for (int i = 0; i < set.getSetSize(); i++) {
                            if (getCardValue(setFight.getCardId(0)) <= getCardValue(set.getCardId(i))) {
                                startIndex = i;
                                break;
                            }
                        }
                        if (set.getSetSize() - startIndex >= setFight.getSetSize()) {
                            boolean isChoose = true;
                            for (int i = startIndex; i < startIndex + setFight.getSetSize(); i++) {
                                listBlock.add(set.getCardId(i));
                                if (getCardValue(set.getCardId(i)) < getCardValue(setFight.getCardId(i - startIndex))) {
                                    isChoose = false;
                                    break;
                                }
                            }
                            if (isChoose) {
//                                Debug.d("set :" + set.toString());
                                return listBlock;
                            }
                        }

                    }
                }

            }
        }
        listBlock.clear();
        return listBlock;
    }

    private List<Integer> chooseBlockCard2(CardSet setFight) {
        // chan bo
        List<Integer> listBlock = new LinkedList<Integer>();
//        Debug.d("set fight :" + setFight.toString());
        for (CardSet set : listCardSets) {
            if (set.getType() == setFight.getType()
                    && set.getSetSize() >= setFight.getSetSize()) {
                listBlock.clear();
                if (set.getType() == CardSet.PAIR) {
                    boolean isChoose = true;
                    if (getCardValue(set.getCardId(0)) < getCardValue(setFight.getCardId(0))) {
                        isChoose = false;
                    } else if (getCardValue(set.getCardId(0)) == getCardValue(setFight.getCardId(0))) {
                        int setSize = setFight.getSetSize();
                        if (setFight.getCardId(setSize - 1) / 13 > set.getCardId(setSize - 1) / 13) {
                            listBlock.addAll(set.getListCards());
                        }
                    } else if (getCardValue(set.getCardId(0)) > getCardValue(setFight.getCardId(0))) {
                        int setSize = setFight.getSetSize();
                        for (int i = 0; i < setSize; i++) {
                            listBlock.add(set.getCardId(i));
                        }

                    }
                    if (isChoose) {
//                        Debug.d("set :" + set.toString());
                        return listBlock;
                    }
                } else {
                    int startIndex = 0;
                    int setFightSize = setFight.getSetSize();
                    for (int i = 0; i < set.getSetSize(); i++) {
                        if (getCardValue(setFight.getCardId(0)) <= getCardValue(set.getCardId(i))) {
                            startIndex = i;
                            break;
                        }
                    }

                    int lastCardIndex = startIndex + setFightSize - 1;
                    if (set.getSetSize() - startIndex >= setFightSize) {
                        int rank1 = getCardRank(set.getCardId(lastCardIndex));
                        int rank2 = getCardRank(setFight.getCardId(setFightSize - 1));
                        if ((rank1 > rank2)
                                || (rank1 == rank2
                                && set.getCardId(lastCardIndex) / 13 < setFight.getCardId(setFightSize - 1) / 13)) {
                            boolean isChoose = true;
                            for (int i = startIndex; i < startIndex + setFight.getSetSize(); i++) {
                                listBlock.add(set.getCardId(i));
                                if (getCardValue(set.getCardId(i)) < getCardValue(setFight.getCardId(i - startIndex))) {
                                    isChoose = false;
                                    break;
                                }
                            }
                            if (isChoose) {
//                                Debug.d("set :" + set.toString());
                                return listBlock;
                            }
                        }
                    }

                }

            }
        }
        listBlock.clear();
        return listBlock;
    }

    public int getSuggestCard2(int cardFight) {
        int[] listCards = new int[listCardIds.size()];
        for (int i = 0; i < listCardIds.size(); i++) {
            listCards[i] = listCardIds.get(i);
        }
        //chan 1 con
        int numberCards = listCards.length;
        int minBlockCard = -1;
        if (cardFight % 13 == 0) {
            for (int i = 0; i < numberCards; i++) {
                if (listCards[i] % 13 == 1) {
                    if (minBlockCard == -1
                            || getCardValue(minBlockCard) > getCardValue(listCards[i])
                            || (getCardValue(minBlockCard) == getCardValue(listCards[i])
                            && minBlockCard / 13 < listCards[i] / 13)) {
                        minBlockCard = listCards[i];
                    }
                } else if (listCards[i] % 13 == 0 && listCards[i] / 13 < cardFight / 13) {
                    int minValue = getCardValue(minBlockCard);
                    int cardValue = getCardValue(listCards[i]);
                    if (minBlockCard == -1
                            || minValue > cardValue
                            || (cardValue == minValue
                            && minBlockCard / 13 < listCards[i] / 13)) {
                        minBlockCard = listCards[i];
                    }
                }
            }
        } else if (cardFight % 13 == 1) {
            for (int i = 0; i < numberCards; i++) {
                if (listCards[i] % 13 == 1 && listCards[i] / 13 < cardFight / 13) {
                    if (minBlockCard == -1 || minBlockCard / 13 > listCards[i] / 13) {
                        minBlockCard = listCards[i];
                    }
                }
            }
        } else {
            for (int i = 0; i < numberCards; i++) {
                int cardValue = getCardValue(listCards[i]);
                if ((getCardValue(cardFight) < cardValue)
                        || (getCardValue(cardFight) == cardValue && cardFight / 13 > listCards[i] / 13)) {
                    int minValue = getCardValue(minBlockCard);
                    if ((minBlockCard == -1)
                            || (minValue > cardValue)) {
                        minBlockCard = listCards[i];
                    } else if (minValue == cardValue
                            && minBlockCard / 13 < listCards[i] / 13) {
                        minBlockCard = listCards[i];
                    }
                }
            }
        }

//        Debug.d("");
//        Debug.d("card fight id :" + cardFight);
//        Debug.d("card fight :" + Card.getName(cardFight));
//        if (minBlockCard != -1) {
//            Card.showName(minBlockCard);
//        }
        return minBlockCard;
    }

    public int getSuggestCard(int cardFight) {
        int[] listCards = new int[listCardIds.size()];
        for (int i = 0; i < listCardIds.size(); i++) {
            listCards[i] = listCardIds.get(i);
        }
        //chan 1 con
        int numberCards = listCards.length;
        int minBlockCard = -1;
        if (cardFight % 13 == 0) {
            for (int i = 0; i < numberCards; i++) {
                if (listCards[i] % 13 == 1) {
                    if (minBlockCard == -1 || minBlockCard / 13 < listCards[i] / 13) {
                        minBlockCard = listCards[i];
                    }
                }
            }
        } else if (cardFight % 13 == 1) {
            for (int i = 0; i < numberCards; i++) {
                if (listCards[i] % 13 == 1 && listCards[i] / 13 < cardFight / 13) {
                    if (minBlockCard == -1 || minBlockCard / 13 < listCards[i] / 13) {
                        minBlockCard = listCards[i];
                    }
                }
            }
        } else {
            for (int i = 0; i < numberCards; i++) {
                if ((cardFight / 13 == listCards[i] / 13
                        && getCardValue(cardFight) < getCardValue(listCards[i]))
                        || listCards[i] % 13 == 1) {
                    if (minBlockCard == -1 || getCardValue(listCards[i]) < getCardValue(minBlockCard)) {
                        minBlockCard = listCards[i];
                    }
                }
            }
        }

//        Debug.d("");
//        Debug.d("card fight id :" + cardFight);
//        Debug.d("card fight :" + Card.getName(cardFight));
        if (minBlockCard != -1) {
            Card.showName(minBlockCard);
        }
        return minBlockCard;
    }

    private int getCardValue(int cardId) {
        return (cardId - 2 + 13) % 13;
    }

    private void extractFlush(int[] listCards) {
        int numberCards = listCards.length;
        for (int i = 0; i < numberCards; i++) {
            for (int j = i + 1; j < numberCards; j++) {
                if (listCards[i] / 13 > listCards[j] / 13
                        || (listCards[i] / 13 == listCards[j] / 13
                        && (listCards[i] - 2 + 13) % 13 > (listCards[j] - 2 + 13) % 13)) {
                    swap(i, j, listCards);
                }
            }
        }
//        printListCardId(listCards);
        for (int i = 0; i < numberCards; i++) {
            int step = 0;
            int cardId = (listCards[i] - 2 + 13) % 13;
            for (int j = i + 1; j < numberCards; j++) {
                if (cardId + (j - i) == (listCards[j] - 2 + 13) % 13 && listCards[i] / 13 == listCards[j] / 13) {
                    step++;
                } else {
                    j = numberCards;
                }
            }
//            Debug.d("day :" + step);
            if (step != 0) {
                int[] flsush = new int[step + 1];
                for (int k = i; k <= i + step; k++) {
                    flsush[k - i] = listCards[k];
                }
                if (step >= 2) {
                    CardSet flushSet = new CardSet(flsush, CardSet.FLUSH);
                    listCardSets.add(flushSet);
                }
                i = i + step;
            }
        }
    }

    private void extractPair(int[] listCards) {
        int numberCards = listCards.length;
        for (int i = 0; i < numberCards; i++) {
            for (int j = i + 1; j < numberCards; j++) {
                if (getCardValue(listCards[i]) > getCardValue(listCards[j])
                        || (getCardValue(listCards[i]) == getCardValue(listCards[j])
                        && listCards[i] / 13 < listCards[j] / 13)) {
                    int temp = listCards[j];
                    listCards[j] = listCards[i];
                    listCards[i] = temp;
                }
            }
        }
        //tim phom ngang
        for (int i = 0; i < numberCards; i++) {
            int cardId = listCards[i];
            int step = 0;
            for (int j = i + 1; j < numberCards; j++) {
                if (cardId % 13 == listCards[j] % 13) {
                    if (j < numberCards - 1 && cardId % 13 == listCards[j + 1] % 13) {
                        if (j < numberCards - 2 && cardId % 13 == listCards[j + 2] % 13) {
                            step = 3;
                        } else {
                            step = 2;
                        }
                    } else {
                        step = 1;
                    }
                    int[] pair = new int[step + 1];
                    for (int k = i; k <= i + step; k++) {
                        pair[k - i] = listCards[k];
                    }
                    if (step >= 1) {
                        CardSet pairSet = new CardSet(pair, CardSet.PAIR);
                        listCardSets.add(pairSet);
                    }
                    j = numberCards;
                    i = i + step;
                }
            }
        }
    }

    private void swap(int i, int j, int[] listCards) {
        int temp = listCards[j];
        listCards[j] = listCards[i];
        listCards[i] = temp;
    }

    public List<Integer> getSuggestFourOfKind() {
        listCardSets = new LinkedList<CardSet>();
        int[] listCards = new int[listCardIds.size()];
        for (int i = 0; i < listCardIds.size(); i++) {
            listCards[i] = listCardIds.get(i);
        }
        extractPair(listCards);
        List<Integer> listBlock = new LinkedList<Integer>();
        for (CardSet set : listCardSets) {
            if (set.getSetSize() == 4 && set.getType() == CardSet.PAIR) {
//                Debug.d("set :" + set.toString());
                listBlock.addAll(set.getListCards());
                break;
            }
        }
        return listBlock;
    }

    public int getSugesstMinCard() {
        int min = -1;
        for (Integer card : listCardIds) {
            if (min == -1 || (getCardValue(card) < getCardValue(min))) {
                min = card;
            }
        }
        return min;
    }

    private void extractSpecialFlush(int[] listCards) {
        int numberCards = listCards.length;
        for (int i = 0; i < numberCards; i++) {
            for (int j = i + 1; j < numberCards; j++) {
                int rank1 = getCardRank(listCards[i]);
                int rank2 = getCardRank(listCards[j]);
                if (rank1 > rank2) {
                    swap(i, j, listCards);
                } else if (rank1 == rank2
                        && (listCards[i] / 13 > listCards[j] / 13)) {
                    swap(i, j, listCards);
                }
            }
        }
//        Debug.d("");
        for (int i = 0; i < numberCards; i++) {
            int step = 0;
            int numberSameValue = 0;
            int cardId = (listCards[i] - 2 + 13) % 13;
            for (int j = i + 1; j < numberCards; j++) {
                int cardRankCheck = getCardRank(listCards[j]);
                if (cardId + (j - i) - numberSameValue == cardRankCheck) {
                    step++;
                } else if (cardId + (j - i) - 1 - numberSameValue == cardRankCheck) {
                    numberSameValue++;
                } else {
                    j = numberCards;
                }
            }
            if (step >= 2) {
                int[] flush = new int[step + 1];
                int rankStart = getCardRank(listCards[i]);
                int delta = 0;
                for (int k = i; k <= i + step + numberSameValue; k++) {
                    int rankNext = getCardRank(listCards[k]);
                    if (rankNext == rankStart + k - i - delta) {
                        flush[k - i - delta] = listCards[k];
//                        Debug.n(Card.getRank(listCards[k]) + Card.getSuit(listCards[k]));
                    } else if (rankNext == rankStart + k - i - 1 - delta) {
                        delta++;
                    }
                }
                CardSet flushSet = new CardSet(flush, CardSet.FLUSH);
                listCardSets.add(flushSet);
                i = i + step + numberSameValue;
            }
        }

    }

    private void extractSpecialPair(int[] listCards) {
        int numberCards = listCards.length;
        for (int i = 0; i < numberCards; i++) {
            for (int j = i + 1; j < numberCards; j++) {
                if (getCardValue(listCards[i]) > getCardValue(listCards[j])
                        || (getCardValue(listCards[i]) == getCardValue(listCards[j])
                        && listCards[i] / 13 < listCards[j] / 13)) {
                    int temp = listCards[j];
                    listCards[j] = listCards[i];
                    listCards[i] = temp;
                }
            }
        }
        //tim phom ngang
        for (int i = 0; i < numberCards; i++) {
            int cardId = listCards[i];
            int step = 0;
            for (int j = i + 1; j < numberCards; j++) {
                if (cardId % 13 == listCards[j] % 13) {
                    if (j < numberCards - 1 && cardId % 13 == listCards[j + 1] % 13) {
                        if (j < numberCards - 2 && cardId % 13 == listCards[j + 2] % 13) {
                            step = 3;
                        } else {
                            step = 2;
                        }
                    } else {
                        step = 1;
                    }
                    int[] pair = new int[step + 1];
                    for (int k = i; k <= i + step; k++) {
                        pair[k - i] = listCards[k];
                    }
                    if (step >= 1) {
                        CardSet pairSet = new CardSet(pair, CardSet.PAIR);
                        listCardSets.add(pairSet);
                    }
                    j = numberCards;
                    i = i + step;
                }
            }
        }
    }

    private int getCardRank(int cardId) {
        return (cardId - 2 + 13) % 13;
    }
}
